#include "ShaderManager.h"
#include <iostream>
#include <sstream>
#include "GDCpp/Runtime/ResourcesLoader.h"

using namespace std;

ShaderManager::ShaderManager() {}

std::shared_ptr<sf::Shader> ShaderManager::GetSFMLShader(
    const std::vector<gd::String>& shaders) {
  if (alreadyLoadedShader.find(shaders) != alreadyLoadedShader.end())
    return alreadyLoadedShader[shaders].lock();

  // Loading a new (compilation of) shader(s)
  std::vector<gd::String> declarations;
  gd::String mainFunctions;

  std::shared_ptr<sf::Shader> shader(new sf::Shader);

  for (std::size_t i = 0; i < shaders.size(); ++i) {
    gd::String file = gd::ResourcesLoader::Get()->LoadPlainText(shaders[i]);

    std::istringstream linesStream(file.ToLocale().c_str());

    bool isInMainFunction = false;
    std::string line;
    while (linesStream.good()) {
      getline(linesStream, line);
      if (line == "void main()") {
        if (!isInMainFunction)
          isInMainFunction = true;
        else
          std::cout << "Main function declared more than one time."
                    << std::endl;
      } else if (!isInMainFunction) {
        if (std::find(declarations.begin(),
                      declarations.end(),
                      gd::String::FromLocale(line) + "\n") ==
            declarations.end())
          declarations.push_back(gd::String::FromLocale(line) + "\n");
      } else
        mainFunctions += gd::String::FromLocale(line) + "\n";
    }
  }

  gd::String shaderSource;
  for (std::size_t i = 0; i < declarations.size(); ++i)
    shaderSource += declarations[i];
  shaderSource += "\nvoid main()\n{" + mainFunctions + "}";
  std::cout << "ShaderSource:" << shaderSource << std::endl;
  shader->loadFromMemory(shaderSource.c_str(), sf::Shader::Fragment);

  alreadyLoadedShader[shaders] = shader;

  return shader;
}
